﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NeurOthello.Logic;
using NeurOthello.NNetwork;
using System.IO;

namespace NeurOthello
{
    class Program
    {
        static void Main(string[] args)
        {
            Othello othello = new Bitboard();
            NeuroPlayer player = new NeuroPlayer(othello);
            //Network net = new Network(1, 2, new int[2] {1, 1});
            MiniMax minmax = new MiniMax(othello);
            MiniMax minmax3 = new MiniMax(othello);
            //MiniMax nnMini = new MiniMax(othello, new NNHeuristic("network500000.nnt"));
            //MiniMax Mini60 = new MiniMax(othello, new NNHeuristic("network-60130.500000.nnt"));
            int nTGames = 100000, inc = 1000, n = 0;

            //player.LoadNetwork("nyanetwerketplusturn63000.nnt");
            MiniMax playerMinmax = new MiniMax(othello, new NNHeuristic(player.Network));
            //player.LoadNetwork("network1025000.nnt");
            //System.Console.Out.WriteLine(net.GetNetworkLine());
            //player.ExportNetwork("othello1mil.nnt");
            // System.Console.Out.WriteLine(test.GetNetworkLine());
            // player.SaveNetwork("transfer600k.nnt");
            //test.Save("loltest.nnt");
            int bG = 0; int wG = 0; int dG = 0;
            int tbG = 0, twG = 0, tdG = 0;
            System.Console.Out.WriteLine("testing");
            bG = 0; wG = 0; dG = 0;

            for (int i = 0; i < 200; i++)
            {
                int t = (othello.playGame(player, minmax));
                if (t == 1)
                    bG++;
                else if (t == 2)
                    wG++;
                else dG++;
            }
            System.Console.Out.WriteLine("played " + 200 + " test games, black: " + bG + " white: " + wG + " draw: " + dG);
            while (true)
            {
                tbG = 0; twG = 0; tdG = 0;
                for (int i = n * inc; i < inc * (n + 1); i++)
                {
                    int t = othello.playTrainingGame(player, Network.HalfLife(0.8, 1500, i), Network.HalfLife(0.8, 2000, i));
                    if (t == 1)
                        tbG++;
                    else if (t == 2)
                        twG++;
                    else tdG++;
                }
                n++;


                System.Console.Out.WriteLine("played " + inc * n + " training games, black: " + tbG + " white: " + twG + " draw: " + tdG);
                player.SaveNetwork("nyanetwerketplusturn" + n * inc + ".nnt");
                System.Console.Out.WriteLine("testing");
                bG = 0; wG = 0; dG = 0;

                for (int i = 0; i < 200; i++)
                {
                    int t = (othello.playGame(player, minmax));
                    if (t == 1)
                        bG++;
                    else if (t == 2)
                        wG++;
                    else dG++;
                }
                System.Console.Out.WriteLine("played " + 200 + " test games, black: " + bG + " white: " + wG + " draw: " + dG);
                // 
            }
            System.Console.In.ReadLine();

        }


    }
}



/*Othello othello = new Bitboard();
NeuroPlayer player = new NeuroPlayer(othello);
Network net = new Network(1, 2, new int[2] {1, 1});
MiniMax minmax = new MiniMax(othello);
MiniMax nnMini = new MiniMax(othello, new NNHeuristic("network500000.nnt"));
MiniMax Mini60 = new MiniMax(othello, new NNHeuristic("network-60130.500000.nnt"));
int nTGames = 2000000, inc = 25000, n = 41;

//Network test = Network.Load("loltest.nnt");
player.LoadNetwork("network1025000.nnt");
//System.Console.Out.WriteLine(net.GetNetworkLine());
player.ExportNetwork("othello1mil.nnt");
// System.Console.Out.WriteLine(test.GetNetworkLine());
// player.SaveNetwork("transfer600k.nnt");
//test.Save("loltest.nnt");
int bG = 0; int wG = 0; int dG = 0;            
int tbG = 0, twG = 0, tdG = 0;

while (true)
{
    tbG = 0; twG = 0; tdG = 0;
    for (int i = n*inc; i < inc*(n+1); i++)
    {
        int t = othello.playTrainingGame(player, 0.08 + (1 / (1 + Math.Exp((i * 11 / nTGames) - 4))), 0.1 + (1 / (1 + Math.Exp((i * 4 / nTGames)))));
        if (t == 1)
            tbG++;
        else if (t == 2)
            twG++;
        else tdG++;
    }
    n++;

                
    System.Console.Out.WriteLine("played " + inc*n + " training games, black: " + tbG + " white: " + twG + " draw: " + tdG);
    player.SaveNetwork("network"+n*inc+".nnt");
   /* System.Console.Out.WriteLine("testing");
    bG = 0; wG = 0; dG = 0;
               
    for (int i = 0; i < 200; i++)
    {
        int t = (othello.playGame(Mini60, nnMini));
        if (t == 1)
            bG++;
        else if (t == 2)
            wG++;
        else dG++;
    }
   // System.Console.Out.WriteLine("played " + 100 + " test games, black: " + bG + " white: " + wG + " draw: " + dG);
   // 
}           
*/


/* 
 List<TrainingSet> trainingSets = new List<TrainingSet>();
            StreamReader readData = new StreamReader("iris.data");
            Network network = new Network(4, 3, new int[1] { 6 });

            while (readData.Peek() >= 0)
            {
                string[] set = readData.ReadLine().Split(',');
                double[] inp = new double[4];
                for (int i = 0; i < 4; i++)
                    inp[i] = 0.1 * double.Parse(set[i], System.Globalization.CultureInfo.InvariantCulture);

                double[] outp = null;
                switch (set[4])
                {
                    case "Iris-setosa":
                        outp = new double[3] { 1, 0, 0 };
                        break;
                    case "Iris-versicolor":
                        outp = new double[3] { 0, 1, 0 };
                        break;
                    case "Iris-virginica":
                        outp = new double[3] { 0, 0, 1 };
                        break;
                }

                trainingSets.Add(new TrainingSet(inp, outp));
            }


            foreach (TrainingSet set in trainingSets)
            {
                network.ProcessInput(set.Inputs, set.Outputs, 0.5);
            }

            Random rand = new Random();
            int r = 0;
            for (int i = 0; i < 250000; i++)
            {
                r = rand.Next(0, 150);
                network.ProcessInput(trainingSets[r].Inputs, trainingSets[r].Outputs, 0.1);
            }

            double[] outs = network.ProcessInput(new double[4] { 0.67, 0.30, 0.52, 0.23 }); // 3

            System.Console.Out.WriteLine(outs[0] + " " + outs[1] + " " + outs[2]);

            outs = network.ProcessInput(new double[4] { 0.47, 0.32, 0.16, 0.02 }); //1

            System.Console.Out.WriteLine(outs[0] + " " + outs[1] + " " + outs[2]);


            outs = network.ProcessInput(new double[4] { 0.61, 0.28, 0.40, 0.13 }); //2

            System.Console.Out.WriteLine(outs[0] + " " + outs[1] + " " + outs[2]);

 */

/*
            Network network = new Network(2, 1, new int[1] { 5 });

           TrainingSet[] sets = new TrainingSet[4];
           sets[0] = new TrainingSet(new double[] { 0, 0 }, new double[] { 0 });
           sets[1] = new TrainingSet(new double[] { 0, 1 }, new double[] { 0 });
           sets[2] = new TrainingSet(new double[] { 1, 0 }, new double[] { 0 });
           sets[3] = new TrainingSet(new double[] { 1, 1 }, new double[] { 1 });

           Random rand = new Random();
           int r = 0;
           for (int i = 0; i < 10000; i++)
           {
               r = rand.Next(0, 4);
               network.ProcessInput(sets[r].Inputs, sets[r].Outputs, 0.5);
           }



           System.Console.Out.WriteLine(network.ProcessInput(new double[] { 0, 1 })[0]);
           System.Console.Out.WriteLine(network.ProcessInput(new double[] { 0, 0 })[0]);
           System.Console.Out.WriteLine(network.ProcessInput(new double[] { 1, 0 })[0]);
           System.Console.Out.WriteLine(network.ProcessInput(new double[] { 1, 1 })[0]);

          
           for (int i = 0; i < 100000; i++)
           {
               r = rand.Next(0, 4);
               network.ProcessInput(sets[r].Inputs, sets[r].Outputs, 0.5);
           }



           System.Console.Out.WriteLine(network.ProcessInput(new double[] { 0, 1 })[0]);
           System.Console.Out.WriteLine(network.ProcessInput(new double[] { 0, 0 })[0]);
           System.Console.Out.WriteLine(network.ProcessInput(new double[] { 1, 0 })[0]);
           System.Console.Out.WriteLine(network.ProcessInput(new double[] { 1, 1 })[0]);
           System.Console.In.ReadLine();
*/

/*Othello othello = new Bitboard();
NeuroPlayer player = new NeuroPlayer(othello);
MiniMax minmax = new MiniMax(othello);


int nTGames = 20000;


int tbG = 0, twG = 0, tdG = 0; 
for (int i = 0; i < 10000; i++)
{
    int t = othello.playTrainingGame(player, 1 / (1 + Math.Exp((i * 11/nTGames) -4)));
    if (t == 1)
        tbG++;
    if (t == 2)
        twG++;
    else tdG++;
}

System.Console.Out.WriteLine("played "+10000+" training games, black: " + tbG + " white: " + twG + " draw: " + tdG);

            

System.Console.Out.WriteLine("testing");
int bG = 0; int wG = 0; int dG = 0; 
int m = 100;
for (int i = 0; i < m; i++)
{
    int t = (othello.playGame(player, minmax));
    if (t == 1)
        bG++;
    if (t == 2)
        wG++;
    else dG++;
}
System.Console.Out.WriteLine("played "+m+" test games, black: " + bG + " white: " + wG + " draw: " + dG);
player.SaveNetwork("network10000.nnt");


     
for (int i = 10000; i < 25000; i++)
{
    int t = othello.playTrainingGame(player, 1 / (1 + Math.Exp((i * 11 / nTGames) - 4)));
    if (t == 1)
        tbG++;
    if (t == 2)
        twG++;
    else tdG++;
}

System.Console.Out.WriteLine("played " + 25000 + " training games, black: " + tbG + " white: " + twG + " draw: " + tdG);



System.Console.Out.WriteLine("testing");
bG = 0; wG = 0; dG = 0;
m = 250;
for (int i = 0; i < m; i++)
{
    int t = (othello.playGame(player, minmax));
    if (t == 1)
        bG++;
    if (t == 2)
        wG++;
    else dG++;
}
System.Console.Out.WriteLine("played " + m + " test games, black: " + bG + " white: " + wG + " draw: " + dG);

player.SaveNetwork("network25000.nnt");


           
for (int i = 25000; i < 50000; i++)
{
    int t = othello.playTrainingGame(player, 1 / (1 + Math.Exp((i * 11 / nTGames) - 4)));
    if (t == 1)
        tbG++;
    if (t == 2)
        twG++;
    else tdG++;
}

System.Console.Out.WriteLine("played " + 50000 + " training games, black: " + tbG + " white: " + twG + " draw: " + tdG);



System.Console.Out.WriteLine("testing");
bG = 0; wG = 0; dG = 0;
m = 500;
for (int i = 0; i < m; i++)
{
    int t = (othello.playGame(player, minmax));
    if (t == 1)
        bG++;
    if (t == 2)
        wG++;
    else dG++;
}
System.Console.Out.WriteLine("played " + m + " test games, black: " + bG + " white: " + wG + " draw: " + dG);

player.SaveNetwork("network50000.nnt");


for (int i = 50000; i < 100000; i++)
{
    int t = othello.playTrainingGame(player, 1 / (1 + Math.Exp((i * 11 / nTGames) - 4)));
    if (t == 1)
        tbG++;
    if (t == 2)
        twG++;
    else tdG++;
}

System.Console.Out.WriteLine("played " + 100000 + " training games, black: " + tbG + " white: " + twG + " draw: " + tdG);



System.Console.Out.WriteLine("testing");
bG = 0; wG = 0; dG = 0;
m = 200;
for (int i = 0; i < m; i++)
{
    int t = (othello.playGame(player, minmax));
    if (t == 1)
        bG++;
    if (t == 2)
        wG++;
    else dG++;
}
System.Console.Out.WriteLine("played " + m + " test games, black: " + bG + " white: " + wG + " draw: " + dG);

player.SaveNetwork("network100000.nnt");


            

//  player.LoadNetwork("network100000.nnt");

int tbG = 0, twG = 0, tdG = 0;
for (int i = 0; i < 1000; i++)
{
    int t = othello.playTrainingGame(player, 1 / (1 + Math.Exp((i * 11 / nTGames) - 4)), 1 / (1 + Math.Exp((i * 4 / nTGames))));
    if (t == 1)
        tbG++;
    else if (t == 2)
        twG++;
    else tdG++;
}
            
System.Console.Out.WriteLine("played " + 1000 + " training games, black: " + tbG + " white: " + twG + " draw: " + tdG);



System.Console.Out.WriteLine("testing");
int bG = 0; int wG = 0; int dG = 0;
int m = 100;
for (int i = 0; i < m; i++)
{
    int t = (othello.playGame(player, minmax));
    if (t == 1)
        bG++;
    else if (t == 2)
        wG++;
    else dG++;
}
System.Console.Out.WriteLine("played " + m + " test games, black: " + bG + " white: " + wG + " draw: " + dG);
player.SaveNetwork("network1000.nnt");



for (int i = 1000; i < 10000; i++)
{
    int t = othello.playTrainingGame(player, 1 / (1 + Math.Exp((i * 11 / nTGames) - 4)), 1 / (1 + Math.Exp((i * 4 / nTGames))));
    if (t == 1)
        tbG++;
    else if (t == 2)
        twG++;
    else tdG++;
}

System.Console.Out.WriteLine("played " + 10000 + " training games, black: " + tbG + " white: " + twG + " draw: " + tdG);



System.Console.Out.WriteLine("testing");
bG = 0; wG = 0; dG = 0;
m = 100;
for (int i = 0; i < m; i++)
{
    int t = (othello.playGame(player, minmax));
    if (t == 1)
        bG++;
    else if (t == 2)
        wG++;
    else dG++;
}
System.Console.Out.WriteLine("played " + m + " test games, black: " + bG + " white: " + wG + " draw: " + dG);

player.SaveNetwork("network10001.nnt");

*/